/*
	File: scripts/main_scene.nut
	Author: Astrofra
*/

Include("scripts/polygonizer.nut")

g_simple_shader		<-	0

/*!
	@short	MainScene
	@author	Astrofra
*/
class	MainScene
{

	grid_handler			=	0

	function	OnSetup(scene)
	{
		// Tell the renderer that we need the frame buffer as a texture.
		RendererRegistrySetKey(g_render, "FrameBufferAsTexture", true)
		g_simple_shader	= ResourceFactoryLoadShader(g_factory, "shaders/shader.nsa")

		grid_handler = MetaBallGrid()
		grid_handler.AddMetaBall(Vector(), Mtr(1.0))
		grid_handler.AddMetaBall(Vector(-1,0,0), Mtr(0.5))
		grid_handler.AddMetaBall(Vector(1,0,0), Mtr(0.45))
	}

	function	OnUpdate(scene)
	{
		local	_rand_v = Vector()
		_rand_v.x = Rand(-1,1)
		_rand_v.y = Rand(-1,1)
		_rand_v.z = Rand(-1,1)
		_rand_v = _rand_v.Normalize().Scale(0.5)

		grid_handler.MetaBallSetPosition(0, grid_handler.MetaBallGetPosition(0).Lerp(0.8, _rand_v))

		grid_handler.Update()
	}

	function	OnRenderUser(scene)
	{
		RendererSetIdentityWorldMatrix(g_render)
		grid_handler.Render()
	}

}

class	MetaBallGrid
{
	grid		=	0

	grid_size	=	0
	ball_list	=	0
	subdiv		=	11

	p			=	0

	constructor()
	{
		grid_size	=	Vector(2,2,2)
		p			=	Vector()
		ball_list	=	[]

		grid		=	array(GetGridIndex(subdiv,subdiv,subdiv) + 1, 0)
		
	}

	function	AddMetaBall(_position = Vector(), _radius = Mtr(1.0))
	{
		ball_list.append({shape = "sphere", position = _position, radius = _radius})
	}

	function	MetaBallSetPosition(idx = 0, _pos = Vector())
	{
		ball_list[idx].position = _pos
	}

	function	MetaBallGetPosition(idx = 0)
	{
		return ball_list[idx].position
	}

	function	Render()
	{
		local	i,j,k
		for(i = 0; i < subdiv - 1; i++)
			for(j = 0; j < subdiv - 1; j++)
				for(k = 0; k < subdiv - 1; k++)
				{
					//	Build a 8 point gridcell.
					local	gridcell = GRIDCELL()

					gridcell.p[0] = clone(grid[GetGridIndex(i,j,k + 1)].position)
					gridcell.p[1] = clone(grid[GetGridIndex(i + 1,j,k + 1)].position)
					gridcell.p[2] = clone(grid[GetGridIndex(i + 1,j,k)].position)
					gridcell.p[3] = clone(grid[GetGridIndex(i,j,k)].position)

					gridcell.val[0] = grid[GetGridIndex(i,j,k + 1)].isolevel
					gridcell.val[1] = grid[GetGridIndex(i + 1,j,k + 1)].isolevel
					gridcell.val[2] = grid[GetGridIndex(i + 1,j,k)].isolevel
					gridcell.val[3] = grid[GetGridIndex(i,j,k)].isolevel

					gridcell.p[4] = clone(grid[GetGridIndex(i,j + 1,k + 1)].position)
					gridcell.p[5] = clone(grid[GetGridIndex(i + 1,j + 1,k + 1)].position)
					gridcell.p[6] = clone(grid[GetGridIndex(i + 1,j + 1,k)].position)
					gridcell.p[7] = clone(grid[GetGridIndex(i,j + 1,k)].position)

					gridcell.val[4] = grid[GetGridIndex(i,j + 1,k + 1)].isolevel
					gridcell.val[5] = grid[GetGridIndex(i + 1,j + 1,k + 1)].isolevel
					gridcell.val[6] = grid[GetGridIndex(i + 1,j + 1,k)].isolevel
					gridcell.val[7] = grid[GetGridIndex(i,j + 1,k)].isolevel

					Polygonise(gridcell, 0.5)
				}		
	}

	function	Update()
	{
		local	i,j,k
		for(i = 0, p.x = grid_size.x * -0.5; p.x < grid_size.x * 0.5 ; i++, p.x += grid_size.x / subdiv.tofloat())
			for(j = 0, p.y = grid_size.y * -0.5; p.y < grid_size.y * 0.5 ; j++, p.y += grid_size.y / subdiv.tofloat())
				for(k = 0, p.z = grid_size.z * -0.5; p.z < grid_size.z * 0.5 ; k++, p.z += grid_size.z / subdiv.tofloat())
				{
					local	_level = 0.0
					foreach(ball in ball_list)
						_level += Clamp(RangeAdjust(p.Dist(ball.position), 0.0, ball.radius, 1.0, 0.0), 0.0, 1.0)

//					if (_level > 0.1)
//						RendererDrawLineColored(g_render, p, p + Vector(0, 0.01, 0), Vector(_level,_level,_level,1.0))

					grid[GetGridIndex(i,j,k)] = { position = clone(p), isolevel = _level}
				}
	}

	function	GetGridIndex(i,j,k)
	{
		return (i + (j * subdiv) + (k * subdiv * subdiv))
	}
}
